package com.service.business.trading.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Maps;
import com.service.business.base.dto.LoginUserSession;
import com.service.business.support.SessionUtil;
import com.service.business.trading.controller.rep.TradingSpotPairsRep;
import com.service.business.trading.controller.rep.TradingSpotTradeRep;
import com.service.business.trading.service.TradingSpotOrderService;
import com.service.business.trading.service.TradingSpotPairsService;
import com.service.business.trading.service.TradingSpotTradesService;
import com.service.core.rest.request.PageRequest;
import com.service.core.rest.response.CommonPageRep;
import com.service.dao.mapper.TradingSpotTradesMapper;
import com.service.dao.model.TradingSpotOrder;
import com.service.dao.model.TradingSpotTrades;
import com.service.match.common.entity.SpotTradeVo;
import com.service.match.common.utils.TradingSpotUtils;
import com.service.utility.modelmapper.ModelMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("tradingSpotTradesService")
public class TradingSpotTradesServiceImpl extends ServiceImpl<TradingSpotTradesMapper, TradingSpotTrades> implements TradingSpotTradesService {

    @Autowired
    private TradingSpotPairsService pairsService;
    @Autowired
    private TradingSpotOrderService spotOrderService;

    @Autowired
    private SessionUtil sessionUtil;

    @Override
    public Map<String, BigDecimal> getActualTimePrice() {
        Map<String, BigDecimal> result = Maps.newHashMap();
        List<TradingSpotPairsRep> pairsReps = pairsService.listPairs();
        pairsReps.parallelStream().forEach(item -> {
            TradingSpotTrades trade = getLastTrade(item.getSymbol());
            if (ObjectUtils.isEmpty(trade)) {
                return;
            }
            result.put(item.getCoinsName(), trade.getOrderPrice());
        });
        return result;
    }

    @Override
    public TradingSpotTrades getLastTrade(String symbol) {
        return getOne(new QueryWrapper<TradingSpotTrades>().lambda()
                .eq(TradingSpotTrades::getSymbol, symbol).orderByDesc(TradingSpotTrades::getId).last("limit 1"));
    }


    @Override
    public SpotTradeVo getLastTradeVo(String symbol) {
        TradingSpotTrades spotTrades = getLastTrade(symbol);
        return ObjectUtils.isEmpty(spotTrades) ? null : ModelMapperUtil.map(spotTrades, SpotTradeVo.class);
    }

    @Override
    public CommonPageRep<TradingSpotTradeRep> pageSpotTrades(String orderNo, PageRequest pageReq) {
        LoginUserSession session = sessionUtil.getUser();
        TradingSpotOrder spotOrder = spotOrderService.getSpotOrderByNo(orderNo, session.getUserId());
        Page<TradingSpotTrades> page = PageHelper.startPage(pageReq.getPageNo(), pageReq.getPageSize());
        LambdaQueryWrapper<TradingSpotTrades> lambdaQueryWrapper = new QueryWrapper<TradingSpotTrades>().lambda();
        if (TradingSpotUtils.isBuy(spotOrder.getTradeType())) {
            lambdaQueryWrapper.eq(TradingSpotTrades::getBuyOrderId, spotOrder.getId());
        } else {
            lambdaQueryWrapper.eq(TradingSpotTrades::getSellOrderId, spotOrder.getId());
        }
        list(lambdaQueryWrapper);
        return CommonPageRep.buildResultRep(page, page.getResult().stream().map(item -> {
            TradingSpotTradeRep resultItem = ModelMapperUtil.map(item, TradingSpotTradeRep.class);
            if (TradingSpotUtils.isBuy(spotOrder.getTradeType())) {
                resultItem.setFee(item.getBuyFee());
            } else {
                resultItem.setFee(item.getSellFee());
            }
            resultItem.setCoinsName(spotOrder.getCoinsName());
            resultItem.setTradeCoinsName(spotOrder.getTradeCoinsName());
            return resultItem;
        }).collect(Collectors.toList()));
    }

    @Override
    public List<TradingSpotTrades> listTrades(Integer orderId, Boolean isBuy) {
        LambdaQueryWrapper<TradingSpotTrades> lambdaQueryWrapper = new QueryWrapper<TradingSpotTrades>().lambda();
        if (isBuy) {
            lambdaQueryWrapper.eq(TradingSpotTrades::getBuyOrderId, orderId);
        } else {
            lambdaQueryWrapper.eq(TradingSpotTrades::getSellOrderId, orderId);
        }
        return list(lambdaQueryWrapper);
    }
}
